package com.wzh.project.redis.utils;

import java.io.Serializable;
import java.util.List;
import java.util.UUID;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.wzh.project.common.Constants;
import com.wzh.project.redis.bean.RedisMessage;
import com.wzh.project.redis.context.RedisContext;
import com.wzh.project.redis.handle.RedisReplyHandler;
import com.wzh.project.utils.BinaryTransferUtils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;

public class JedisUtils {
	
	private static final Logger logger=LogManager.getLogger(JedisUtils.class);
	
	/**
	 * 
	 * @param name				配置文件标识
	 * @param queueName			队列名字
	 * @param req				消息的对象
	 * @param corllerationId	消息id
	 * @param isReply			是否需要回复
	 * @return 
	 * @throws Exception
	 */
	public static Object sendObj(String name,String queueName,String serviceName,Serializable req,String uuid,String flag,boolean isReply)
			throws Exception {
		RedisMessage objMessage = new RedisMessage();
		objMessage.setObj(req);
		objMessage.setReply(isReply);
		objMessage.setReplyQueueName(ReplyQueueUtil.getReplyQueue());
		objMessage.setServiceName(serviceName);
		objMessage.setDirection(flag);
		objMessage.setUuid(uuid);
		Jedis resource = null;
		//如果传递的队列名为null使用默认的队列名
		String sendQueueName=queueName==null?Constants.REDIS_QUEUE:queueName;
		try {
			byte[] bmessage = BinaryTransferUtils.transferToBinaryByteArray(objMessage);
			Object jedis = RedisContext.getInstance().getJedis(name);
			logger.debug("向redis队列："+sendQueueName+"发送消息！");
			if (jedis instanceof JedisPool) {
			  	JedisPool jedisPool=(JedisPool)jedis;
			  	logger.debug("redis使用单机池资源发送");
			  	resource = jedisPool.getResource();
			  	logger.debug("已经获取池资源，准备发送消息");
			  	resource.lpush(sendQueueName.getBytes(), bmessage);
			}else {
				logger.debug("redis使用集群示例发送！");
				JedisCluster jcr = (JedisCluster)jedis;
				logger.debug("准备发送消息");
				jcr.lpush(sendQueueName.getBytes(), bmessage); 
			}
			if (isReply) {
				//如果需要回复,同步等待结果返回
				RedisReplyHandler.getInit().getLocksMap().put(uuid, uuid);
				return RedisReplyHandler.getInit().handle(uuid,Constants.TIMEOUT);
			}
		} catch (Exception e) {
			logger.error("使用jedis发送消息异常",e);
			throw new Exception("使用jedis发送消息异常",e);
		}finally {
			if (resource!=null) {
				resource.close();
			}
		}
		return null;
	}
	
	public static void receive(String name) {
    	while(true) {
    		try {
				Thread.sleep(1000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
    		RedisContext jc = RedisContext.getInstance();
    		Object o = null;
    		Jedis resource = null;
	        try {
	        	o = jc.getJedis(name);
	            if (o instanceof JedisPool) {
	            	JedisPool jedisPool=(JedisPool)o;
	            	resource = jedisPool.getResource();
	            	List<byte[]> list = resource.brpop(0, Constants.REDIS_QUEUE.getBytes());
	            	dealMessage(list);
	            }else {
	            	JedisCluster jcr = (JedisCluster)o;
	            	List<byte[]> list = jcr.brpop(0, Constants.REDIS_QUEUE.getBytes());
	            	dealMessage(list);
	            }
	        } catch (Exception e) {
	            logger.error("从频道获取消息错误，队列为："+Constants.REDIS_QUEUE, e);
	        } finally {
	        	  if( o==null ) {
	        		  return;
	        	  }
	        	  if (o instanceof JedisPool) {
		            	if(resource!=null) {
		            		resource.close();
		            	}
		            }
	        }
    	}
	}
	
	/**
	 * 处理结果数据
	 * @param list
	 */
	private static void dealMessage(List<byte[]> list) {
		logger.debug("队列中接收到的消息为:"+list.get(0));
	}
	/**
	 * 向缓存中存放数据
	 * @param name 		缓redis对象
	 * @param key		存放的key
	 * @param req		存放的对象
	 * @param isExist	是否存在 true:已经存在该key 进行更新，false不存在该key 进行创建
	 * @param expx		ex:秒--px:毫秒
	 * @param time		有效时间
	 * @throws Exception
	 */
	public static void setCacheData(String name,String key,Serializable req,boolean isExist,String expx,long time) throws Exception{
		Jedis resource = null;
		String nxxx="NX";//不存在则创建
		if (isExist) {
			nxxx="XX";//存在才进行更新
		}
		try {
			byte[] value = BinaryTransferUtils.transferToBinaryByteArray(req);
			Object jedis = RedisContext.getInstance().getJedis(name);
			if (jedis instanceof JedisPool) {
			  	JedisPool jedisPool=(JedisPool)jedis;
			  	logger.debug("redis使用单机池资源存放消息");
			  	resource = jedisPool.getResource();
			  	logger.debug("已经获取池资源，准备存放消息");
			  	if (!isExist) {
					resource.del(key.getBytes());
				}
			  //	resource.set(key.getBytes(), value, nxxx.getBytes(), expx.getBytes(), time);
			}else {
				logger.debug("redis使用集群存放！");
				JedisCluster jcr = (JedisCluster)jedis;
				if (!isExist) {
					jcr.del(key.getBytes());
				}
				//jcr.set(key.getBytes(), value, nxxx.getBytes(), expx.getBytes(), time);
			}
		} catch (Exception e) {
			logger.error("使用jedis存放消息异常",e);
			throw new Exception("使用jedis存放消息异常",e);
		}finally {
			if (resource!=null) {
				resource.close();
			}
		}
	}
	/**
	 * 从缓存中获取数据
	 * @return
	 * @throws Exception
	 */
	public static Object getCacheData(String name,String key) throws Exception{
		Jedis resource = null;
		byte[] value = null;
		try {
			Object jedis = RedisContext.getInstance().getJedis(name);
			if (jedis instanceof JedisPool) {
			  	JedisPool jedisPool=(JedisPool)jedis;
			  	logger.debug("redis使用单机池资源获取消息");
			  	resource = jedisPool.getResource();
			  	logger.debug("已经获取池资源，准备获取消息");
			  	value=resource.get(key.getBytes());
			}else {
				logger.debug("redis使用集群获取！");
				JedisCluster jcr = (JedisCluster)jedis;
				value=jcr.get(key.getBytes());
			}
		} catch (Exception e) {
			logger.error("使用jedis存放消息异常",e);
			throw new Exception("使用jedis存放消息异常",e);
		}finally {
			if (resource!=null) {
				resource.close();
			}
		}
//		try {
//			//自己测试使用
//			return new String(value);
//		} catch (Exception e) {
//			// TODO: handle exception
//		}
		return BinaryTransferUtils.transferByteArrayToObject(value);
	}
	
	/**
	 * 删除对应的key
	 * @param name
	 * @param key
	 * @throws Exception
	 */
	public static void deleteKey(String name,String key) throws Exception{
		Jedis resource = null;
		try {
			Object jedis = RedisContext.getInstance().getJedis(name);
			if (jedis instanceof JedisPool) {
			  	JedisPool jedisPool=(JedisPool)jedis;
			  	resource = jedisPool.getResource();
			  	resource.del(key.getBytes());
			}else {
				JedisCluster jcr = (JedisCluster)jedis;
				jcr.del(key.getBytes());
			}
		} catch (Exception e) {
			throw new Exception("使用jedis删除key异常",e);
		}finally {
			if (resource!=null) {
				resource.close();
			}
		}
	}
}
